﻿Public Class UIElement

	Public Parent As UIElement
	Public Rectangle As Rectangle
	Public TopHost As WPFHost

	ReadOnly Property Host As WPFHost
		Get
			If Not Parent Is Nothing Then Return Parent.Host
			Return TopHost
		End Get
	End Property

	Overridable Sub Resize(Rectangle As Rectangle)
		Me.Rectangle = Rectangle
		RaiseEvent Relocated(Me, Nothing)
		Invalidate()
	End Sub

	Sub Initialize(Child As UIElement)
		Child.Parent = Me
	End Sub

	Public Sub Invalidate()
		If Not Host Is Nothing Then Host.Invalidate(Rectangle)
	End Sub

	Property Dock As Docking = Docking.None

	Function MeasureText(Text As String, Font As Font) As SizeF
		Return Host.MeasureText(Text, Font)
	End Function

	Overridable ReadOnly Property Height As Integer
		Get
			Return Padding.Vertical + Spacing.Vertical + (From b In Borders Select b.Thickness.Vertical).Sum
		End Get
	End Property

	Overridable ReadOnly Property Width As Integer
		Get
			Return Padding.Horizontal + Spacing.Horizontal + (From b In Borders Select b.Thickness.Horizontal).Sum
		End Get
	End Property

	Dim _Font As Font
	Property Font As Font
		Get
			If Not _Font Is Nothing Then Return _Font
			If Parent Is Nothing Then Return If(Host Is Nothing, Nothing, Host.Font)
			Return Parent.Font
		End Get
		Set(value As Font)
			_Font = value
		End Set
	End Property

	Property IgnoreMouse As Boolean

	Enum Docking
		None
		Top
		Bottom
		Left
		Right
	End Enum

	ReadOnly Property PaddedRectangle As Rectangle
		Get
			Dim R = Rectangle
			R.Offset(Spacing.Left, Spacing.Top)
			R.Width -= Spacing.Horizontal
			R.Height -= Spacing.Vertical
			Return R
		End Get
	End Property

	ReadOnly Property ContentRectangle As Rectangle
		Get
			Dim R = Rectangle
			R.Offset(Spacing.Left + Padding.Left + (From b In Borders Select b.Thickness.Left).Sum, Spacing.Top + Padding.Top + (From b In Borders Select b.Thickness.Top).Sum)
			R.Width -= Spacing.Horizontal + Padding.Horizontal + (From b In Borders Select b.Thickness.Horizontal).Sum
			R.Height -= Spacing.Vertical + Padding.Vertical + (From b In Borders Select b.Thickness.Vertical).Sum
			Return R
		End Get
	End Property

	Overridable Sub Draw(e As PaintEventArgs)
		'Dim rr = Rectangle
		'rr.Inflate(2, 2)
		'e.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(Rnd(1) * 255, Rnd(1) * 255, Rnd(1) * 255)), rr)
		If Not Visible Then Return
		e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
		If Not Background Is Nothing Then
			Dim R = PaddedRectangle
			R.Offset((From b In Borders Select b.Thickness.Left).Sum, (From b In Borders Select b.Thickness.Top).Sum)
			R.Width -= (From b In Borders Select b.Thickness.Horizontal).Sum
			R.Height -= (From b In Borders Select b.Thickness.Vertical).Sum
			e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
			Dim Curve = If(Borders.Count = 0, 0, Borders.Last.Corners.Left)
			FillRoundRect(e.Graphics, R, New SolidBrush(CType(Background, ColorBrush).Color), Curve)
			e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.None
		End If
		Dim Rect = PaddedRectangle
		For Each Border In Borders
			Dim R = Rect
			Rect.Offset(Border.Thickness.Left, Border.Thickness.Top)
			Rect.Width -= Border.Thickness.Horizontal
			Rect.Height -= Border.Thickness.Vertical
			If Border.Thickness.Left Mod 2 = 1 Then
				e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.None
			Else
				e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.HighQuality
			End If
			If Border.Thickness.Left > 1 Then
				R.Offset(Border.Thickness.Left / 2, Border.Thickness.Left / 2)
				R.Width -= Border.Thickness.Left / 2
				R.Height -= Border.Thickness.Left / 2
			End If
			R.Width -= 1
			R.Height -= 1
			DrawRoundRect(e.Graphics, R, New Pen(Border.Color, Border.Thickness.Left), Border.Corners.Left)
			e.Graphics.PixelOffsetMode = Drawing2D.PixelOffsetMode.None
		Next
	End Sub

	Overridable Sub Measure()

	End Sub

	Dim _Visible As Boolean = True
	Property Visible As Boolean
		Get
			Return _Visible
		End Get
		Set(value As Boolean)
			If value = _Visible Then Return
			_Visible = value
			If Not Host Is Nothing Then Host.Remeasure()
		End Set
	End Property

	Dim _Indent As Point
	Property Indent As Point
		Get
			Return _Indent
		End Get
		Set(value As Point)
			If _Indent = value Then Return
			_Indent = value
			'If Not Host Is Nothing Then Host.Remeasure()
		End Set
	End Property


	Dim _Padding As Padding
	Property Padding As Padding
		Get
			Return _Padding
		End Get
		Set(value As Padding)
			_Padding = value
			If Not Host Is Nothing Then Host.Remeasure()
		End Set
	End Property

	Dim _Spacing As Padding
	Property Spacing As Padding
		Get
			Return _Spacing
		End Get
		Set(value As Padding)
			_Spacing = value
			If Not Host Is Nothing Then Host.Remeasure()
		End Set
	End Property

	Dim _Background As UIBrush
	Property Background As UIBrush
		Get
			Return _Background
		End Get
		Set(value As UIBrush)
			_Background = value
			Invalidate()
		End Set
	End Property

	Dim MouseIn As Boolean

	Overridable Sub CheckMouseEvent(e As MouseEventArgs, Type As String)
		If IgnoreMouse Then Return
		If Not Visible Then Return
		If Type = "leave" Then
			If Not MouseIn Then Return
			MouseIn = False
			If Rectangle.Contains(e.Location) Then
				RaiseEvent MouseMove(Me, e)
			Else
				RaiseEvent MouseLeave(Me, e)
			End If
		ElseIf Type = "enter" Then
			If Not MouseIn Then
				If Rectangle.Contains(e.Location) Then
					MouseIn = True
					RaiseEvent MouseEnter(Me, e)
				End If
			End If
		ElseIf Type = "down" Then
			If Rectangle.Contains(e.Location) Then
				RaiseEvent MouseDown(Me, e)
			End If
		End If
	End Sub

	Event MouseEnter(sender As Object, e As MouseEventArgs)
	Event MouseLeave(sender As Object, e As MouseEventArgs)
	Event MouseMove(sender As Object, e As MouseEventArgs)
	Event MouseDown(sender As Object, e As MouseEventArgs)
	Event Relocated(sender As UIElement, e As EventArgs)

	Dim Borders As New List(Of BorderInfo)

	Sub AddBorder(Color As Color, Thickness As Padding, Corners As Padding)
		Dim Border As New BorderInfo
		Border.Color = Color
		Border.Thickness = Thickness
		Border.Corners = Corners
		Borders.Add(Border)
	End Sub

	Class BorderInfo
		Public Color As Color
		Public Thickness As Padding
		Public Corners As Padding
	End Class

End Class

